import java.util.*;
import java.text.*;
import java.util.Date;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.*;

// 主程序入口
public class CinemaManagementSystem {
    private static Scanner scanner = new Scanner(System.in);

    public static void main(String[] args) {
        // 初始化数据库
        DBUtils.initDatabase();

        // 如果是首次运行，初始化测试数据
        if (DBUtils.isFirstRun()) {
            initializeTestData();
        }

        while (true) {
            System.out.println("\n=== 影院管理系统 ===");
            System.out.println("1. 管理员登录");
            System.out.println("2. 经理登录");
            System.out.println("3. 前台登录");
            System.out.println("4. 退出系统");
            System.out.print("请选择: ");

            int choice;
            try {
                choice = scanner.nextInt();
                scanner.nextLine(); // 消费换行符
            } catch (InputMismatchException e) {
                System.out.println("输入错误，请输入数字1-4！");
                scanner.nextLine(); // 清除错误输入
                continue;
            }

            switch (choice) {
                case 1:
                    adminLogin();
                    break;
                case 2:
                    managerLogin();
                    break;
                case 3:
                    frontDeskLogin();
                    break;
                case 4:
                    System.out.println("谢谢使用，再见！");
                    scanner.close();
                    DBUtils.closeConnection();
                    System.exit(0);
                    break;
                default:
                    System.out.println("无效选择，请重试！");
            }
        }
    }

    // 初始化测试数据
    private static void initializeTestData() {
        // 添加测试用户（密码已加密）
        DBUtils.addUser(new User("admin", EncryptionUtils.md5Encrypt("admin123"), "ADMIN"));
        DBUtils.addUser(new User("manager1", EncryptionUtils.md5Encrypt("manager123"), "MANAGER"));
        DBUtils.addUser(new User("front1", EncryptionUtils.md5Encrypt("front123"), "FRONTDESK"));

        // 添加测试电影
        DBUtils.addMovie(new Movie("M001", "复仇者联盟", "科幻/动作", 143));
        DBUtils.addMovie(new Movie("M002", "流浪地球", "科幻/冒险", 125));
        DBUtils.addMovie(new Movie("M003", "哪吒之魔童降世", "动画/喜剧", 110));

        // 添加测试影厅
        DBUtils.addHall(new Hall("H001", "一号厅", 100));
        DBUtils.addHall(new Hall("H002", "二号厅", 80));
        DBUtils.addHall(new Hall("H003", "三号厅", 50));

        // 添加测试场次
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
            DBUtils.addScreening(new Screening(
                    "S001",
                    "M001",
                    "H001",
                    sdf.parse("2025-01-15 14:30"),
                    50.0
            ));
            DBUtils.addScreening(new Screening(
                    "S002",
                    "M002",
                    "H002",
                    sdf.parse("2025-01-15 16:45"),
                    45.0
            ));
            DBUtils.addScreening(new Screening(
                    "S003",
                    "M003",
                    "H003",
                    sdf.parse("2025-01-15 19:00"),
                    40.0
            ));
        } catch (ParseException e) {
            System.out.println("初始化场次数据出错: " + e.getMessage());
        }
    }

    // 管理员登录
    private static void adminLogin() {
        System.out.println("\n=== 管理员登录 ===");
        System.out.print("用户名: ");
        String username = scanner.nextLine();
        System.out.print("密码: ");
        String password = scanner.nextLine();

        User user = DBUtils.getUserByUsername(username);
        // 密码验证时使用加密后的值比较
        if (user != null && user.getPassword().equals(EncryptionUtils.md5Encrypt(password)) && user.getRole().equals("ADMIN")) {
            System.out.println("登录成功！");
            AdminMenu.showMenu(user);
        } else {
            System.out.println("用户名或密码错误，或无管理员权限！");
        }
    }

    // 经理登录
    private static void managerLogin() {
        System.out.println("\n=== 经理登录 ===");
        System.out.print("用户名: ");
        String username = scanner.nextLine();
        System.out.print("密码: ");
        String password = scanner.nextLine();

        User user = DBUtils.getUserByUsername(username);
        if (user != null && user.getPassword().equals(EncryptionUtils.md5Encrypt(password)) && user.getRole().equals("MANAGER")) {
            System.out.println("登录成功！");
            ManagerMenu.showMenu(user);
        } else {
            System.out.println("用户名或密码错误，或无经理权限！");
        }
    }

    // 前台登录
    private static void frontDeskLogin() {
        System.out.println("\n=== 前台登录 ===");
        System.out.print("用户名: ");
        String username = scanner.nextLine();
        System.out.print("密码: ");
        String password = scanner.nextLine();

        User user = DBUtils.getUserByUsername(username);
        if (user != null && user.getPassword().equals(EncryptionUtils.md5Encrypt(password)) && user.getRole().equals("FRONTDESK")) {
            System.out.println("登录成功！");
            FrontDeskMenu.showMenu(user);
        } else {
            System.out.println("用户名或密码错误，或无前台权限！");
        }
    }
}

// 加密工具类
class EncryptionUtils {
    // MD5加密
    public static String md5Encrypt(String input) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] messageDigest = md.digest(input.getBytes());

            // 转换为十六进制字符串
            StringBuilder hexString = new StringBuilder();
            for (byte b : messageDigest) {
                String hex = Integer.toHexString(0xFF & b);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            return hexString.toString();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }
}

// 数据库工具类
class DBUtils {
    private static final String DB_URL = "jdbc:sqlite:cinema.db";
    private static Connection connection;

    // 初始化数据库连接和表结构
    public static void initDatabase() {
        try {
            // 加载SQLite JDBC驱动
            Class.forName("org.sqlite.JDBC");
            connection = DriverManager.getConnection(DB_URL);

            // 创建表结构
            createTables();
        } catch (Exception e) {
            System.err.println("数据库初始化错误: " + e.getMessage());
            e.printStackTrace();
        }
    }

    // 检查是否首次运行（用户表为空）
    public static boolean isFirstRun() {
        try {
            String sql = "SELECT COUNT(*) FROM users";
            PreparedStatement pstmt = connection.prepareStatement(sql);
            ResultSet rs = pstmt.executeQuery();

            if (rs.next() && rs.getInt(1) == 0) {
                return true;
            }
        } catch (SQLException e) {
            System.err.println("检查首次运行错误: " + e.getMessage());
        }
        return false;
    }

    // 创建所有表结构
    private static void createTables() {
        String[] createTableSQLs = {
                // 用户表
                "CREATE TABLE IF NOT EXISTS users (" +
                        "username TEXT PRIMARY KEY," +
                        "password TEXT NOT NULL," +
                        "role TEXT NOT NULL)",

                // 电影表
                "CREATE TABLE IF NOT EXISTS movies (" +
                        "movie_id TEXT PRIMARY KEY," +
                        "title TEXT NOT NULL," +
                        "genre TEXT NOT NULL," +
                        "duration INTEGER NOT NULL)",

                // 影厅表
                "CREATE TABLE IF NOT EXISTS halls (" +
                        "hall_id TEXT PRIMARY KEY," +
                        "name TEXT NOT NULL," +
                        "capacity INTEGER NOT NULL)",

                // 场次表
                "CREATE TABLE IF NOT EXISTS screenings (" +
                        "screening_id TEXT PRIMARY KEY," +
                        "movie_id TEXT NOT NULL," +
                        "hall_id TEXT NOT NULL," +
                        "start_time DATETIME NOT NULL," +
                        "price REAL NOT NULL," +
                        "FOREIGN KEY(movie_id) REFERENCES movies(movie_id)," +
                        "FOREIGN KEY(hall_id) REFERENCES halls(hall_id))",

                // 票表
                "CREATE TABLE IF NOT EXISTS tickets (" +
                        "ticket_id TEXT PRIMARY KEY," +
                        "screening_id TEXT NOT NULL," +
                        "seat_number TEXT NOT NULL," +
                        "is_child_ticket INTEGER NOT NULL," +
                        "is_refunded INTEGER NOT NULL," +
                        "purchase_time DATETIME NOT NULL," +
                        "FOREIGN KEY(screening_id) REFERENCES screenings(screening_id))",

                // 日志表
                "CREATE TABLE IF NOT EXISTS logs (" +
                        "log_id TEXT PRIMARY KEY," +
                        "operator TEXT NOT NULL," +
                        "operation TEXT NOT NULL," +
                        "details TEXT NOT NULL," +
                        "timestamp DATETIME NOT NULL)"
        };

        try {
            Statement stmt = connection.createStatement();
            for (String sql : createTableSQLs) {
                stmt.execute(sql);
            }
        } catch (SQLException e) {
            System.err.println("创建表错误: " + e.getMessage());
        }
    }

    // 关闭数据库连接
    public static void closeConnection() {
        try {
            if (connection != null) {
                connection.close();
            }
        } catch (SQLException e) {
            System.err.println("关闭数据库连接错误: " + e.getMessage());
        }
    }

    // 用户相关操作
    public static void addUser(User user) {
        String sql = "INSERT INTO users(username, password, role) VALUES(?, ?, ?)";

        try {
            PreparedStatement pstmt = connection.prepareStatement(sql);
            pstmt.setString(1, user.getUsername());
            pstmt.setString(2, user.getPassword());
            pstmt.setString(3, user.getRole());
            pstmt.executeUpdate();
        } catch (SQLException e) {
            System.err.println("添加用户错误: " + e.getMessage());
        }
    }

    public static User getUserByUsername(String username) {
        String sql = "SELECT * FROM users WHERE username = ?";

        try {
            PreparedStatement pstmt = connection.prepareStatement(sql);
            pstmt.setString(1, username);
            ResultSet rs = pstmt.executeQuery();

            if (rs.next()) {
                return new User(
                        rs.getString("username"),
                        rs.getString("password"),
                        rs.getString("role")
                );
            }
        } catch (SQLException e) {
            System.err.println("查询用户错误: " + e.getMessage());
        }
        return null;
    }

    public static List<User> getAllUsers() {
        List<User> users = new ArrayList<>();
        String sql = "SELECT * FROM users";

        try {
            Statement stmt = connection.createStatement();
            ResultSet rs = stmt.executeQuery(sql);

            while (rs.next()) {
                users.add(new User(
                        rs.getString("username"),
                        rs.getString("password"),
                        rs.getString("role")
                ));
            }
        } catch (SQLException e) {
            System.err.println("查询所有用户错误: " + e.getMessage());
        }
        return users;
    }

    public static boolean deleteUser(String username) {
        String sql = "DELETE FROM users WHERE username = ?";

        try {
            PreparedStatement pstmt = connection.prepareStatement(sql);
            pstmt.setString(1, username);
            int rowsAffected = pstmt.executeUpdate();
            return rowsAffected > 0;
        } catch (SQLException e) {
            System.err.println("删除用户错误: " + e.getMessage());
            return false;
        }
    }

    public static boolean updateUserPassword(String username, String newPassword) {
        String sql = "UPDATE users SET password = ? WHERE username = ?";

        try {
            PreparedStatement pstmt = connection.prepareStatement(sql);
            pstmt.setString(1, newPassword);
            pstmt.setString(2, username);
            int rowsAffected = pstmt.executeUpdate();
            return rowsAffected > 0;
        } catch (SQLException e) {
            System.err.println("更新用户密码错误: " + e.getMessage());
            return false;
        }
    }

    // 电影相关操作
    public static void addMovie(Movie movie) {
        String sql = "INSERT INTO movies(movie_id, title, genre, duration) VALUES(?, ?, ?, ?)";

        try {
            PreparedStatement pstmt = connection.prepareStatement(sql);
            pstmt.setString(1, movie.getMovieId());
            pstmt.setString(2, movie.getTitle());
            pstmt.setString(3, movie.getGenre());
            pstmt.setInt(4, movie.getDuration());
            pstmt.executeUpdate();
        } catch (SQLException e) {
            System.err.println("添加电影错误: " + e.getMessage());
        }
    }

    public static Movie getMovieById(String movieId) {
        String sql = "SELECT * FROM movies WHERE movie_id = ?";

        try {
            PreparedStatement pstmt = connection.prepareStatement(sql);
            pstmt.setString(1, movieId);
            ResultSet rs = pstmt.executeQuery();

            if (rs.next()) {
                return new Movie(
                        rs.getString("movie_id"),
                        rs.getString("title"),
                        rs.getString("genre"),
                        rs.getInt("duration")
                );
            }
        } catch (SQLException e) {
            System.err.println("查询电影错误: " + e.getMessage());
        }
        return null;
    }

    public static List<Movie> getAllMovies() {
        List<Movie> movies = new ArrayList<>();
        String sql = "SELECT * FROM movies";

        try {
            Statement stmt = connection.createStatement();
            ResultSet rs = stmt.executeQuery(sql);

            while (rs.next()) {
                movies.add(new Movie(
                        rs.getString("movie_id"),
                        rs.getString("title"),
                        rs.getString("genre"),
                        rs.getInt("duration")
                ));
            }
        } catch (SQLException e) {
            System.err.println("查询所有电影错误: " + e.getMessage());
        }
        return movies;
    }

    public static boolean updateMovie(Movie updatedMovie) {
        String sql = "UPDATE movies SET title = ?, genre = ?, duration = ? WHERE movie_id = ?";

        try {
            PreparedStatement pstmt = connection.prepareStatement(sql);
            pstmt.setString(1, updatedMovie.getTitle());
            pstmt.setString(2, updatedMovie.getGenre());
            pstmt.setInt(3, updatedMovie.getDuration());
            pstmt.setString(4, updatedMovie.getMovieId());
            int rowsAffected = pstmt.executeUpdate();
            return rowsAffected > 0;
        } catch (SQLException e) {
            System.err.println("更新电影错误: " + e.getMessage());
            return false;
        }
    }

    public static boolean deleteMovie(String movieId) {
        String sql = "DELETE FROM movies WHERE movie_id = ?";

        try {
            PreparedStatement pstmt = connection.prepareStatement(sql);
            pstmt.setString(1, movieId);
            int rowsAffected = pstmt.executeUpdate();
            return rowsAffected > 0;
        } catch (SQLException e) {
            System.err.println("删除电影错误: " + e.getMessage());
            return false;
        }
    }

    // 影厅相关操作
    public static void addHall(Hall hall) {
        String sql = "INSERT INTO halls(hall_id, name, capacity) VALUES(?, ?, ?)";

        try {
            PreparedStatement pstmt = connection.prepareStatement(sql);
            pstmt.setString(1, hall.getHallId());
            pstmt.setString(2, hall.getName());
            pstmt.setInt(3, hall.getCapacity());
            pstmt.executeUpdate();
        } catch (SQLException e) {
            System.err.println("添加影厅错误: " + e.getMessage());
        }
    }

    public static Hall getHallById(String hallId) {
        String sql = "SELECT * FROM halls WHERE hall_id = ?";

        try {
            PreparedStatement pstmt = connection.prepareStatement(sql);
            pstmt.setString(1, hallId);
            ResultSet rs = pstmt.executeQuery();

            if (rs.next()) {
                return new Hall(
                        rs.getString("hall_id"),
                        rs.getString("name"),
                        rs.getInt("capacity")
                );
            }
        } catch (SQLException e) {
            System.err.println("查询影厅错误: " + e.getMessage());
        }
        return null;
    }

    public static List<Hall> getAllHalls() {
        List<Hall> halls = new ArrayList<>();
        String sql = "SELECT * FROM halls";

        try {
            Statement stmt = connection.createStatement();
            ResultSet rs = stmt.executeQuery(sql);

            while (rs.next()) {
                halls.add(new Hall(
                        rs.getString("hall_id"),
                        rs.getString("name"),
                        rs.getInt("capacity")
                ));
            }
        } catch (SQLException e) {
            System.err.println("查询所有影厅错误: " + e.getMessage());
        }
        return halls;
    }

    public static boolean updateHall(Hall updatedHall) {
        String sql = "UPDATE halls SET name = ?, capacity = ? WHERE hall_id = ?";

        try {
            PreparedStatement pstmt = connection.prepareStatement(sql);
            pstmt.setString(1, updatedHall.getName());
            pstmt.setInt(2, updatedHall.getCapacity());
            pstmt.setString(3, updatedHall.getHallId());
            int rowsAffected = pstmt.executeUpdate();
            return rowsAffected > 0;
        } catch (SQLException e) {
            System.err.println("更新影厅错误: " + e.getMessage());
            return false;
        }
    }

    public static boolean deleteHall(String hallId) {
        String sql = "DELETE FROM halls WHERE hall_id = ?";

        try {
            PreparedStatement pstmt = connection.prepareStatement(sql);
            pstmt.setString(1, hallId);
            int rowsAffected = pstmt.executeUpdate();
            return rowsAffected > 0;
        } catch (SQLException e) {
            System.err.println("删除影厅错误: " + e.getMessage());
            return false;
        }
    }

    // 场次相关操作
    public static void addScreening(Screening screening) {
        String sql = "INSERT INTO screenings(screening_id, movie_id, hall_id, start_time, price) VALUES(?, ?, ?, ?, ?)";

        try {
            PreparedStatement pstmt = connection.prepareStatement(sql);
            pstmt.setString(1, screening.getScreeningId());
            pstmt.setString(2, screening.getMovieId());
            pstmt.setString(3, screening.getHallId());
            pstmt.setString(4, new SimpleDateFormat("yyyy-MM-dd HH:mm").format(screening.getStartTime()));
            pstmt.setDouble(5, screening.getPrice());
            pstmt.executeUpdate();
        } catch (SQLException e) {
            System.err.println("添加场次错误: " + e.getMessage());
        }
    }

    public static Screening getScreeningById(String screeningId) {
        String sql = "SELECT * FROM screenings WHERE screening_id = ?";

        try {
            PreparedStatement pstmt = connection.prepareStatement(sql);
            pstmt.setString(1, screeningId);
            ResultSet rs = pstmt.executeQuery();

            if (rs.next()) {
                return new Screening(
                        rs.getString("screening_id"),
                        rs.getString("movie_id"),
                        rs.getString("hall_id"),
                        new SimpleDateFormat("yyyy-MM-dd HH:mm").parse(rs.getString("start_time")),
                        rs.getDouble("price")
                );
            }
        } catch (Exception e) {
            System.err.println("查询场次错误: " + e.getMessage());
        }
        return null;
    }

    public static List<Screening> getAllScreenings() {
        List<Screening> screenings = new ArrayList<>();
        String sql = "SELECT * FROM screenings";

        try {
            Statement stmt = connection.createStatement();
            ResultSet rs = stmt.executeQuery(sql);

            while (rs.next()) {
                screenings.add(new Screening(
                        rs.getString("screening_id"),
                        rs.getString("movie_id"),
                        rs.getString("hall_id"),
                        new SimpleDateFormat("yyyy-MM-dd HH:mm").parse(rs.getString("start_time")),
                        rs.getDouble("price")
                ));
            }
        } catch (Exception e) {
            System.err.println("查询所有场次错误: " + e.getMessage());
        }
        return screenings;
    }

    public static List<Screening> getScreeningsByMovieId(String movieId) {
        List<Screening> screenings = new ArrayList<>();
        String sql = "SELECT * FROM screenings WHERE movie_id = ?";

        try {
            PreparedStatement pstmt = connection.prepareStatement(sql);
            pstmt.setString(1, movieId);
            ResultSet rs = pstmt.executeQuery();

            while (rs.next()) {
                screenings.add(new Screening(
                        rs.getString("screening_id"),
                        rs.getString("movie_id"),
                        rs.getString("hall_id"),
                        new SimpleDateFormat("yyyy-MM-dd HH:mm").parse(rs.getString("start_time")),
                        rs.getDouble("price")
                ));
            }
        } catch (Exception e) {
            System.err.println("按电影ID查询场次错误: " + e.getMessage());
        }
        return screenings;
    }

    public static boolean updateScreening(Screening screening) {
        String sql = "UPDATE screenings SET movie_id = ?, hall_id = ?, start_time = ?, price = ? WHERE screening_id = ?";

        try {
            PreparedStatement pstmt = connection.prepareStatement(sql);
            pstmt.setString(1, screening.getMovieId());
            pstmt.setString(2, screening.getHallId());
            pstmt.setString(3, new SimpleDateFormat("yyyy-MM-dd HH:mm").format(screening.getStartTime()));
            pstmt.setDouble(4, screening.getPrice());
            pstmt.setString(5, screening.getScreeningId());
            int rowsAffected = pstmt.executeUpdate();
            return rowsAffected > 0;
        } catch (SQLException e) {
            System.err.println("更新场次错误: " + e.getMessage());
            return false;
        }
    }

    public static boolean deleteScreening(String screeningId) {
        String sql = "DELETE FROM screenings WHERE screening_id = ?";

        try {
            PreparedStatement pstmt = connection.prepareStatement(sql);
            pstmt.setString(1, screeningId);
            int rowsAffected = pstmt.executeUpdate();
            return rowsAffected > 0;
        } catch (SQLException e) {
            System.err.println("删除场次错误: " + e.getMessage());
            return false;
        }
    }

    // 票相关操作
    public static void addTicket(Ticket ticket) {
        String sql = "INSERT INTO tickets(ticket_id, screening_id, seat_number, is_child_ticket, is_refunded, purchase_time) VALUES(?, ?, ?, ?, ?, ?)";

        try {
            PreparedStatement pstmt = connection.prepareStatement(sql);
            pstmt.setString(1, ticket.getTicketId());
            pstmt.setString(2, ticket.getScreeningId());
            pstmt.setString(3, ticket.getSeatNumber());
            pstmt.setInt(4, ticket.isChildTicket() ? 1 : 0);
            pstmt.setInt(5, ticket.isRefunded() ? 1 : 0);
            pstmt.setString(6, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(ticket.getPurchaseTime()));
            pstmt.executeUpdate();
        } catch (SQLException e) {
            System.err.println("添加票错误: " + e.getMessage());
        }
    }

    public static Ticket getTicketById(String ticketId) {
        String sql = "SELECT * FROM tickets WHERE ticket_id = ?";

        try {
            PreparedStatement pstmt = connection.prepareStatement(sql);
            pstmt.setString(1, ticketId);
            ResultSet rs = pstmt.executeQuery();

            if (rs.next()) {
                return new Ticket(
                        rs.getString("ticket_id"),
                        rs.getString("screening_id"),
                        rs.getString("seat_number"),
                        rs.getInt("is_child_ticket") == 1,
                        rs.getInt("is_refunded") == 1,
                        new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(rs.getString("purchase_time"))
                );
            }
        } catch (Exception e) {
            System.err.println("查询票错误: " + e.getMessage());
        }
        return null;
    }

    public static List<Ticket> getTicketsByScreeningId(String screeningId) {
        List<Ticket> tickets = new ArrayList<>();
        String sql = "SELECT * FROM tickets WHERE screening_id = ? AND is_refunded = 0";

        try {
            PreparedStatement pstmt = connection.prepareStatement(sql);
            pstmt.setString(1, screeningId);
            ResultSet rs = pstmt.executeQuery();

            while (rs.next()) {
                tickets.add(new Ticket(
                        rs.getString("ticket_id"),
                        rs.getString("screening_id"),
                        rs.getString("seat_number"),
                        rs.getInt("is_child_ticket") == 1,
                        rs.getInt("is_refunded") == 1,
                        new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(rs.getString("purchase_time"))
                ));
            }
        } catch (Exception e) {
            System.err.println("按场次ID查询票错误: " + e.getMessage());
        }
        return tickets;
    }

    public static List<Ticket> getAllTickets() {
        List<Ticket> tickets = new ArrayList<>();
        String sql = "SELECT * FROM tickets";

        try {
            Statement stmt = connection.createStatement();
            ResultSet rs = stmt.executeQuery(sql);

            while (rs.next()) {
                tickets.add(new Ticket(
                        rs.getString("ticket_id"),
                        rs.getString("screening_id"),
                        rs.getString("seat_number"),
                        rs.getInt("is_child_ticket") == 1,
                        rs.getInt("is_refunded") == 1,
                        new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(rs.getString("purchase_time"))
                ));
            }
        } catch (Exception e) {
            System.err.println("查询所有票错误: " + e.getMessage());
        }
        return tickets;
    }

    public static boolean updateTicket(Ticket ticket) {
        String sql = "UPDATE tickets SET is_refunded = ? WHERE ticket_id = ?";

        try {
            PreparedStatement pstmt = connection.prepareStatement(sql);
            pstmt.setInt(1, ticket.isRefunded() ? 1 : 0);
            pstmt.setString(2, ticket.getTicketId());
            int rowsAffected = pstmt.executeUpdate();
            return rowsAffected > 0;
        } catch (SQLException e) {
            System.err.println("更新票状态错误: " + e.getMessage());
            return false;
        }
    }

    // 日志相关操作
    public static void addLogEntry(LogEntry log) {
        String sql = "INSERT INTO logs(log_id, operator, operation, details, timestamp) VALUES(?, ?, ?, ?, ?)";

        try {
            PreparedStatement pstmt = connection.prepareStatement(sql);
            pstmt.setString(1, log.getLogId());
            pstmt.setString(2, log.getOperator());
            pstmt.setString(3, log.getOperation());
            pstmt.setString(4, log.getDetails());
            pstmt.setString(5, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(log.getTimestamp()));
            pstmt.executeUpdate();
        } catch (SQLException e) {
            System.err.println("添加日志错误: " + e.getMessage());
        }
    }

    public static List<LogEntry> getAllLogs() {
        List<LogEntry> logs = new ArrayList<>();
        String sql = "SELECT * FROM logs ORDER BY timestamp DESC";

        try {
            Statement stmt = connection.createStatement();
            ResultSet rs = stmt.executeQuery(sql);

            while (rs.next()) {
                try {
                    logs.add(new LogEntry(
                            rs.getString("log_id"),
                            rs.getString("operator"),
                            rs.getString("operation"),
                            rs.getString("details"),
                            new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(rs.getString("timestamp"))
                    ));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
        } catch (SQLException e) {
            System.err.println("查询所有日志错误: " + e.getMessage());
        }
        return logs;
    }
}

// 用户类
class User {
    private String username;
    private String password;
    private String role; // ADMIN, MANAGER, FRONTDESK

    public User(String username, String password, String role) {
        this.username = username;
        this.password = password;
        this.role = role;
    }

    // Getters and Setters
    public String getUsername() { return username; }
    public void setUsername(String username) { this.username = username; }
    public String getPassword() { return password; }
    public void setPassword(String password) { this.password = password; }
    public String getRole() { return role; }
    public void setRole(String role) { this.role = role; }
}

// 电影类
class Movie {
    private String movieId;
    private String title;
    private String genre;
    private int duration; // 分钟

    public Movie(String movieId, String title, String genre, int duration) {
        this.movieId = movieId;
        this.title = title;
        this.genre = genre;
        this.duration = duration;
    }

    // Getters and Setters
    public String getMovieId() { return movieId; }
    public void setMovieId(String movieId) { this.movieId = movieId; }
    public String getTitle() { return title; }
    public void setTitle(String title) { this.title = title; }
    public String getGenre() { return genre; }
    public void setGenre(String genre) { this.genre = genre; }
    public int getDuration() { return duration; }
    public void setDuration(int duration) { this.duration = duration; }
}

// 影厅类
class Hall {
    private String hallId;
    private String name;
    private int capacity;

    public Hall(String hallId, String name, int capacity) {
        this.hallId = hallId;
        this.name = name;
        this.capacity = capacity;
    }

    // Getters and Setters
    public String getHallId() { return hallId; }
    public void setHallId(String hallId) { this.hallId = hallId; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getCapacity() { return capacity; }
    public void setCapacity(int capacity) { this.capacity = capacity; }
}

// 场次类
class Screening {
    private String screeningId;
    private String movieId;
    private String hallId;
    private Date startTime;
    private double price;

    public Screening(String screeningId, String movieId, String hallId, Date startTime, double price) {
        this.screeningId = screeningId;
        this.movieId = movieId;
        this.hallId = hallId;
        this.startTime = startTime;
        this.price = price;
    }

    // Getters and Setters
    public String getScreeningId() { return screeningId; }
    public void setScreeningId(String screeningId) { this.screeningId = screeningId; }
    public String getMovieId() { return movieId; }
    public void setMovieId(String movieId) { this.movieId = movieId; }
    public String getHallId() { return hallId; }
    public void setHallId(String hallId) { this.hallId = hallId; }
    public Date getStartTime() { return startTime; }
    public void setStartTime(Date startTime) { this.startTime = startTime; }
    public double getPrice() { return price; }
    public void setPrice(double price) { this.price = price; }
}

// 票类
class Ticket {
    private String ticketId;
    private String screeningId;
    private String seatNumber;
    private boolean isChildTicket;
    private boolean isRefunded;
    private Date purchaseTime;

    public Ticket(String ticketId, String screeningId, String seatNumber, boolean isChildTicket, boolean isRefunded, Date purchaseTime) {
        this.ticketId = ticketId;
        this.screeningId = screeningId;
        this.seatNumber = seatNumber;
        this.isChildTicket = isChildTicket;
        this.isRefunded = isRefunded;
        this.purchaseTime = purchaseTime;
    }

    public Ticket(String ticketId, String screeningId, String seatNumber, boolean isChildTicket, Date purchaseTime) {
        this(ticketId, screeningId, seatNumber, isChildTicket, false, purchaseTime);
    }

    // Getters and Setters
    public String getTicketId() { return ticketId; }
    public void setTicketId(String ticketId) { this.ticketId = ticketId; }
    public String getScreeningId() { return screeningId; }
    public void setScreeningId(String screeningId) { this.screeningId = screeningId; }
    public String getSeatNumber() { return seatNumber; }
    public void setSeatNumber(String seatNumber) { this.seatNumber = seatNumber; }
    public boolean isChildTicket() { return isChildTicket; }
    public void setChildTicket(boolean isChildTicket) { this.isChildTicket = isChildTicket; }
    public boolean isRefunded() { return isRefunded; }
    public void setRefunded(boolean isRefunded) { this.isRefunded = isRefunded; }
    public Date getPurchaseTime() { return purchaseTime; }
    public void setPurchaseTime(Date purchaseTime) { this.purchaseTime = purchaseTime; }

    // 获取关联的场次信息
    public Screening getScreening() {
        return DBUtils.getScreeningById(screeningId);
    }
}

// 日志条目类
class LogEntry {
    private String logId;
    private String operator;
    private String operation;
    private String details;
    private Date timestamp;

    public LogEntry(String logId, String operator, String operation, String details, Date timestamp) {
        this.logId = logId;
        this.operator = operator;
        this.operation = operation;
        this.details = details;
        this.timestamp = timestamp;
    }

    public LogEntry(String logId, String operator, String operation, String details) {
        this(logId, operator, operation, details, new Date());
    }

    // Getters
    public String getLogId() { return logId; }
    public String getOperator() { return operator; }
    public String getOperation() { return operation; }
    public String getDetails() { return details; }
    public Date getTimestamp() { return timestamp; }
}

// 管理员菜单类
class AdminMenu {
    private static Scanner scanner = new Scanner(System.in);

    public static void showMenu(User admin) {
        while (true) {
            System.out.println("\n=== 管理员菜单 ===");
            System.out.println("1. 管理用户");
            System.out.println("2. 查看系统日志");
            System.out.println("3. 修改密码");
            System.out.println("4. 退出登录");
            System.out.print("请选择: ");

            int choice;
            try {
                choice = scanner.nextInt();
                scanner.nextLine(); // 消费换行符
            } catch (InputMismatchException e) {
                System.out.println("输入错误，请输入数字1-4！");
                scanner.nextLine(); // 清除错误输入
                continue;
            }

            switch (choice) {
                case 1:
                    manageUsers(admin);
                    break;
                case 2:
                    viewSystemLogs();
                    break;
                case 3:
                    changePassword(admin);
                    break;
                case 4:
                    System.out.println("退出登录成功！");
                    return;
                default:
                    System.out.println("无效选择，请重试！");
            }
        }
    }

    private static void manageUsers(User admin) {
        while (true) {
            System.out.println("\n=== 用户管理 ===");
            System.out.println("1. 查看所有用户");
            System.out.println("2. 添加新用户");
            System.out.println("3. 删除用户");
            System.out.println("4. 返回上一级");
            System.out.print("请选择: ");

            int choice;
            try {
                choice = scanner.nextInt();
                scanner.nextLine(); // 消费换行符
            } catch (InputMismatchException e) {
                System.out.println("输入错误，请输入数字1-4！");
                scanner.nextLine(); // 清除错误输入
                continue;
            }

            switch (choice) {
                case 1:
                    listAllUsers();
                    break;
                case 2:
                    addNewUser(admin);
                    break;
                case 3:
                    deleteUser(admin);
                    break;
                case 4:
                    return;
                default:
                    System.out.println("无效选择，请重试！");
            }
        }
    }

    private static void listAllUsers() {
        System.out.println("\n=== 所有用户 ===");
        List<User> users = DBUtils.getAllUsers();
        if (users.isEmpty()) {
            System.out.println("没有用户数据！");
            return;
        }

        System.out.println("用户名\t角色");
        for (User user : users) {
            System.out.println(user.getUsername() + "\t" + user.getRole());
        }
    }

    private static void addNewUser(User admin) {
        System.out.println("\n=== 添加新用户 ===");
        System.out.print("请输入用户名: ");
        String username = scanner.nextLine();

        if (DBUtils.getUserByUsername(username) != null) {
            System.out.println("用户名已存在！");
            return;
        }

        System.out.print("请输入密码: ");
        String password = scanner.nextLine();

        // 密码复杂度检查
        if (password.length() < 6) {
            System.out.println("密码长度不能少于6位！");
            return;
        }

        System.out.println("请选择角色:");
        System.out.println("1. 管理员");
        System.out.println("2. 经理");
        System.out.println("3. 前台");
        System.out.print("请选择: ");

        int roleChoice;
        try {
            roleChoice = scanner.nextInt();
            scanner.nextLine(); // 消费换行符
        } catch (InputMismatchException e) {
            System.out.println("输入错误，请输入数字1-3！");
            scanner.nextLine(); // 清除错误输入
            return;
        }

        String role;
        switch (roleChoice) {
            case 1:
                role = "ADMIN";
                break;
            case 2:
                role = "MANAGER";
                break;
            case 3:
                role = "FRONTDESK";
                break;
            default:
                System.out.println("无效选择，添加失败！");
                return;
        }

        // 密码加密处理
        String encryptedPassword = EncryptionUtils.md5Encrypt(password);
        User newUser = new User(username, encryptedPassword, role);
        DBUtils.addUser(newUser);

        // 记录日志
        String logId = "LOG" + System.currentTimeMillis();
        String details = "添加新用户: " + username + ", 角色: " + role;
        DBUtils.addLogEntry(new LogEntry(logId, admin.getUsername(), "ADD_USER", details));

        System.out.println("用户添加成功！");
    }

    private static void deleteUser(User admin) {
        System.out.println("\n=== 删除用户 ===");
        System.out.print("请输入要删除的用户名: ");
        String username = scanner.nextLine();

        if (username.equals(admin.getUsername())) {
            System.out.println("不能删除当前登录的用户！");
            return;
        }

        boolean success = DBUtils.deleteUser(username);
        if (success) {
            // 记录日志
            String logId = "LOG" + System.currentTimeMillis();
            String details = "删除用户: " + username;
            DBUtils.addLogEntry(new LogEntry(logId, admin.getUsername(), "DELETE_USER", details));

            System.out.println("用户删除成功！");
        } else {
            System.out.println("用户不存在，删除失败！");
        }
    }

    private static void viewSystemLogs() {
        System.out.println("\n=== 系统日志 ===");
        List<LogEntry> logs = DBUtils.getAllLogs();
        if (logs.isEmpty()) {
            System.out.println("没有日志记录！");
            return;
        }

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("时间\t\t\t操作人\t操作类型\t详情");
        for (LogEntry log : logs) {
            System.out.println(
                    sdf.format(log.getTimestamp()) + "\t" +
                            log.getOperator() + "\t" +
                            log.getOperation() + "\t" +
                            log.getDetails()
            );
        }
    }

    static void changePassword(User user) {
        System.out.println("\n=== 修改密码 ===");
        System.out.print("请输入原密码: ");
        String oldPassword = scanner.nextLine();

        // 验证原密码时使用加密
        if (!user.getPassword().equals(EncryptionUtils.md5Encrypt(oldPassword))) {
            System.out.println("原密码错误！");
            return;
        }

        System.out.print("请输入新密码: ");
        String newPassword = scanner.nextLine();

        // 密码复杂度检查
        if (newPassword.length() < 6) {
            System.out.println("密码长度不能少于6位！");
            return;
        }

        System.out.print("请再次输入新密码: ");
        String confirmPassword = scanner.nextLine();

        if (!newPassword.equals(confirmPassword)) {
            System.out.println("两次输入的密码不一致！");
            return;
        }

        // 新密码加密后存储
        String encryptedNewPassword = EncryptionUtils.md5Encrypt(newPassword);
        boolean success = DBUtils.updateUserPassword(user.getUsername(), encryptedNewPassword);

        if (success) {
            user.setPassword(encryptedNewPassword);

            // 记录日志
            String logId = "LOG" + System.currentTimeMillis();
            String details = "用户 " + user.getUsername() + " 修改了密码";
            DBUtils.addLogEntry(new LogEntry(logId, user.getUsername(), "CHANGE_PASSWORD", details));

            System.out.println("密码修改成功！");
        } else {
            System.out.println("密码修改失败！");
        }
    }
}

// 经理菜单类
class ManagerMenu {
    private static Scanner scanner = new Scanner(System.in);

    public static void showMenu(User manager) {
        while (true) {
            System.out.println("\n=== 经理菜单 ===");
            System.out.println("1. 管理电影");
            System.out.println("2. 管理影厅");
            System.out.println("3. 管理场次");
            System.out.println("4. 查看销售统计");
            System.out.println("5. 修改密码");
            System.out.println("6. 退出登录");
            System.out.print("请选择: ");

            int choice;
            try {
                choice = scanner.nextInt();
                scanner.nextLine(); // 消费换行符
            } catch (InputMismatchException e) {
                System.out.println("输入错误，请输入数字1-6！");
                scanner.nextLine(); // 清除错误输入
                continue;
            }

            switch (choice) {
                case 1:
                    manageMovies(manager);
                    break;
                case 2:
                    manageHalls(manager);
                    break;
                case 3:
                    manageScreenings(manager);
                    break;
                case 4:
                    viewSalesStatistics();
                    break;
                case 5:
                    AdminMenu.changePassword(manager);
                    break;
                case 6:
                    System.out.println("退出登录成功！");
                    return;
                default:
                    System.out.println("无效选择，请重试！");
            }
        }
    }

    private static void manageMovies(User manager) {
        while (true) {
            System.out.println("\n=== 电影管理 ===");
            System.out.println("1. 查看所有电影");
            System.out.println("2. 添加新电影");
            System.out.println("3. 修改电影信息");
            System.out.println("4. 删除电影");
            System.out.println("5. 返回上一级");
            System.out.print("请选择: ");

            int choice;
            try {
                choice = scanner.nextInt();
                scanner.nextLine(); // 消费换行符
            } catch (InputMismatchException e) {
                System.out.println("输入错误，请输入数字1-5！");
                scanner.nextLine(); // 清除错误输入
                continue;
            }

            switch (choice) {
                case 1:
                    listAllMovies();
                    break;
                case 2:
                    addNewMovie(manager);
                    break;
                case 3:
                    updateMovie(manager);
                    break;
                case 4:
                    deleteMovie(manager);
                    break;
                case 5:
                    return;
                default:
                    System.out.println("无效选择，请重试！");
            }
        }
    }

    public static void listAllMovies() {
        System.out.println("\n=== 所有电影 ===");
        List<Movie> movies = DBUtils.getAllMovies();
        if (movies.isEmpty()) {
            System.out.println("没有电影数据！");
            return;
        }

        System.out.println("电影ID\t标题\t\t类型\t时长(分钟)");
        for (Movie movie : movies) {
            System.out.println(
                    movie.getMovieId() + "\t" +
                            movie.getTitle() + "\t" +
                            movie.getGenre() + "\t" +
                            movie.getDuration()
            );
        }
    }

    private static void addNewMovie(User manager) {
        System.out.println("\n=== 添加新电影 ===");
        System.out.print("请输入电影ID: ");
        String movieId = scanner.nextLine();

        if (DBUtils.getMovieById(movieId) != null) {
            System.out.println("电影ID已存在！");
            return;
        }

        System.out.print("请输入电影标题: ");
        String title = scanner.nextLine();

        System.out.print("请输入电影类型: ");
        String genre = scanner.nextLine();

        System.out.print("请输入电影时长(分钟): ");
        int duration;
        try {
            duration = scanner.nextInt();
            scanner.nextLine(); // 消费换行符
        } catch (InputMismatchException e) {
            System.out.println("输入错误，请输入数字！");
            scanner.nextLine(); // 清除错误输入
            return;
        }

        Movie newMovie = new Movie(movieId, title, genre, duration);
        DBUtils.addMovie(newMovie);

        // 记录日志
        String logId = "LOG" + System.currentTimeMillis();
        String details = "添加新电影: " + title + " (" + movieId + ")";
        DBUtils.addLogEntry(new LogEntry(logId, manager.getUsername(), "ADD_MOVIE", details));

        System.out.println("电影添加成功！");
    }

    private static void updateMovie(User manager) {
        System.out.println("\n=== 修改电影信息 ===");
        System.out.print("请输入要修改的电影ID: ");
        String movieId = scanner.nextLine();

        Movie movie = DBUtils.getMovieById(movieId);
        if (movie == null) {
            System.out.println("电影不存在！");
            return;
        }

        System.out.println("当前电影信息:");
        System.out.println("标题: " + movie.getTitle());
        System.out.println("类型: " + movie.getGenre());
        System.out.println("时长: " + movie.getDuration() + "分钟");

        System.out.print("请输入新标题(不修改请按回车): ");
        String title = scanner.nextLine();
        if (!title.isEmpty()) {
            movie.setTitle(title);
        }

        System.out.print("请输入新类型(不修改请按回车): ");
        String genre = scanner.nextLine();
        if (!genre.isEmpty()) {
            movie.setGenre(genre);
        }

        System.out.print("请输入新时长(分钟，不修改请输入0): ");
        int duration;
        try {
            duration = scanner.nextInt();
            scanner.nextLine(); // 消费换行符
            if (duration > 0) {
                movie.setDuration(duration);
            }
        } catch (InputMismatchException e) {
            System.out.println("输入错误，时长未修改！");
            scanner.nextLine(); // 清除错误输入
        }

        boolean success = DBUtils.updateMovie(movie);
        if (success) {
            // 记录日志
            String logId = "LOG" + System.currentTimeMillis();
            String details = "修改电影信息: " + movie.getTitle() + " (" + movieId + ")";
            DBUtils.addLogEntry(new LogEntry(logId, manager.getUsername(), "UPDATE_MOVIE", details));

            System.out.println("电影信息修改成功！");
        } else {
            System.out.println("电影信息修改失败！");
        }
    }

    private static void deleteMovie(User manager) {
        System.out.println("\n=== 删除电影 ===");
        System.out.print("请输入要删除的电影ID: ");
        String movieId = scanner.nextLine();

        // 检查是否有关联的场次
        List<Screening> screenings = DBUtils.getScreeningsByMovieId(movieId);
        if (!screenings.isEmpty()) {
            System.out.println("无法删除，该电影存在关联的场次！");
            return;
        }

        Movie movie = DBUtils.getMovieById(movieId);
        if (movie == null) {
            System.out.println("电影不存在！");
            return;
        }

        boolean success = DBUtils.deleteMovie(movieId);
        if (success) {
            // 记录日志
            String logId = "LOG" + System.currentTimeMillis();
            String details = "删除电影: " + movie.getTitle() + " (" + movieId + ")";
            DBUtils.addLogEntry(new LogEntry(logId, manager.getUsername(), "DELETE_MOVIE", details));

            System.out.println("电影删除成功！");
        } else {
            System.out.println("电影删除失败！");
        }
    }

    private static void manageHalls(User manager) {
        while (true) {
            System.out.println("\n=== 影厅管理 ===");
            System.out.println("1. 查看所有影厅");
            System.out.println("2. 添加新影厅");
            System.out.println("3. 修改影厅信息");
            System.out.println("4. 删除影厅");
            System.out.println("5. 返回上一级");
            System.out.print("请选择: ");

            int choice;
            try {
                choice = scanner.nextInt();
                scanner.nextLine(); // 消费换行符
            } catch (InputMismatchException e) {
                System.out.println("输入错误，请输入数字1-5！");
                scanner.nextLine(); // 清除错误输入
                continue;
            }

            switch (choice) {
                case 1:
                    listAllHalls();
                    break;
                case 2:
                    addNewHall(manager);
                    break;
                case 3:
                    updateHall(manager);
                    break;
                case 4:
                    deleteHall(manager);
                    break;
                case 5:
                    return;
                default:
                    System.out.println("无效选择，请重试！");
            }
        }
    }

    public static void listAllHalls() {
        System.out.println("\n=== 所有影厅 ===");
        List<Hall> halls = DBUtils.getAllHalls();
        if (halls.isEmpty()) {
            System.out.println("没有影厅数据！");
            return;
        }

        System.out.println("影厅ID\t名称\t容量");
        for (Hall hall : halls) {
            System.out.println(
                    hall.getHallId() + "\t" +
                            hall.getName() + "\t" +
                            hall.getCapacity()
            );
        }
    }

    private static void addNewHall(User manager) {
        System.out.println("\n=== 添加新影厅 ===");
        System.out.print("请输入影厅ID: ");
        String hallId = scanner.nextLine();

        if (DBUtils.getHallById(hallId) != null) {
            System.out.println("影厅ID已存在！");
            return;
        }

        System.out.print("请输入影厅名称: ");
        String name = scanner.nextLine();

        System.out.print("请输入影厅容量: ");
        int capacity;
        try {
            capacity = scanner.nextInt();
            scanner.nextLine(); // 消费换行符
        } catch (InputMismatchException e) {
            System.out.println("输入错误，请输入数字！");
            scanner.nextLine(); // 清除错误输入
            return;
        }

        Hall newHall = new Hall(hallId, name, capacity);
        DBUtils.addHall(newHall);

        // 记录日志
        String logId = "LOG" + System.currentTimeMillis();
        String details = "添加新影厅: " + name + " (" + hallId + ")";
        DBUtils.addLogEntry(new LogEntry(logId, manager.getUsername(), "ADD_HALL", details));

        System.out.println("影厅添加成功！");
    }

    private static void updateHall(User manager) {
        System.out.println("\n=== 修改影厅信息 ===");
        System.out.print("请输入要修改的影厅ID: ");
        String hallId = scanner.nextLine();

        Hall hall = DBUtils.getHallById(hallId);
        if (hall == null) {
            System.out.println("影厅不存在！");
            return;
        }

        System.out.println("当前影厅信息:");
        System.out.println("名称: " + hall.getName());
        System.out.println("容量: " + hall.getCapacity());

        System.out.print("请输入新名称(不修改请按回车): ");
        String name = scanner.nextLine();
        if (!name.isEmpty()) {
            hall.setName(name);
        }

        System.out.print("请输入新容量(不修改请输入0): ");
        int capacity;
        try {
            capacity = scanner.nextInt();
            scanner.nextLine(); // 消费换行符
            if (capacity > 0) {
                hall.setCapacity(capacity);
            }
        } catch (InputMismatchException e) {
            System.out.println("输入错误，容量未修改！");
            scanner.nextLine(); // 清除错误输入
        }

        boolean success = DBUtils.updateHall(hall);
        if (success) {
            // 记录日志
            String logId = "LOG" + System.currentTimeMillis();
            String details = "修改影厅信息: " + hall.getName() + " (" + hallId + ")";
            DBUtils.addLogEntry(new LogEntry(logId, manager.getUsername(), "UPDATE_HALL", details));

            System.out.println("影厅信息修改成功！");
        } else {
            System.out.println("影厅信息修改失败！");
        }
    }

    private static void deleteHall(User manager) {
        System.out.println("\n=== 删除影厅 ===");
        System.out.print("请输入要删除的影厅ID: ");
        String hallId = scanner.nextLine();

        Hall hall = DBUtils.getHallById(hallId);
        if (hall == null) {
            System.out.println("影厅不存在！");
            return;
        }

        // 检查是否有关联的场次
        boolean hasScreenings = false;
        for (Screening s : DBUtils.getAllScreenings()) {
            if (s.getHallId().equals(hallId)) {
                hasScreenings = true;
                break;
            }
        }

        if (hasScreenings) {
            System.out.println("无法删除，该影厅存在关联的场次！");
            return;
        }

        boolean success = DBUtils.deleteHall(hallId);
        if (success) {
            // 记录日志
            String logId = "LOG" + System.currentTimeMillis();
            String details = "删除影厅: " + hall.getName() + " (" + hallId + ")";
            DBUtils.addLogEntry(new LogEntry(logId, manager.getUsername(), "DELETE_HALL", details));

            System.out.println("影厅删除成功！");
        } else {
            System.out.println("影厅删除失败！");
        }
    }

    private static void manageScreenings(User manager) {
        while (true) {
            System.out.println("\n=== 场次管理 ===");
            System.out.println("1. 查看所有场次");
            System.out.println("2. 添加新场次");
            System.out.println("3. 修改场次信息");
            System.out.println("4. 删除场次");
            System.out.println("5. 返回上一级");
            System.out.print("请选择: ");

            int choice;
            try {
                choice = scanner.nextInt();
                scanner.nextLine(); // 消费换行符
            } catch (InputMismatchException e) {
                System.out.println("输入错误，请输入数字1-5！");
                scanner.nextLine(); // 清除错误输入
                continue;
            }

            switch (choice) {
                case 1:
                    listAllScreenings();
                    break;
                case 2:
                    addNewScreening(manager);
                    break;
                case 3:
                    updateScreening(manager);
                    break;
                case 4:
                    deleteScreening(manager);
                    break;
                case 5:
                    return;
                default:
                    System.out.println("无效选择，请重试！");
            }
        }
    }

    public static void listAllScreenings() {
        System.out.println("\n=== 所有场次 ===");
        List<Screening> screenings = DBUtils.getAllScreenings();
        if (screenings.isEmpty()) {
            System.out.println("没有场次数据！");
            return;
        }

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        System.out.println("场次ID\t电影\t\t影厅\t开始时间\t\t票价");
        for (Screening screening : screenings) {
            Movie movie = DBUtils.getMovieById(screening.getMovieId());
            Hall hall = DBUtils.getHallById(screening.getHallId());

            System.out.println(
                    screening.getScreeningId() + "\t" +
                            (movie != null ? movie.getTitle() : "未知") + "\t" +
                            (hall != null ? hall.getName() : "未知") + "\t" +
                            sdf.format(screening.getStartTime()) + "\t" +
                            screening.getPrice()
            );
        }
    }

    private static void addNewScreening(User manager) {
        System.out.println("\n=== 添加新场次 ===");
        System.out.print("请输入场次ID: ");
        String screeningId = scanner.nextLine();

        if (DBUtils.getScreeningById(screeningId) != null) {
            System.out.println("场次ID已存在！");
            return;
        }

        // 显示所有电影供选择
        listAllMovies();
        System.out.print("请输入电影ID: ");
        String movieId = scanner.nextLine();

        if (DBUtils.getMovieById(movieId) == null) {
            System.out.println("电影不存在！");
            return;
        }

        // 显示所有影厅供选择
        listAllHalls();
        System.out.print("请输入影厅ID: ");
        String hallId = scanner.nextLine();

        if (DBUtils.getHallById(hallId) == null) {
            System.out.println("影厅不存在！");
            return;
        }

        System.out.print("请输入开始时间(格式: yyyy-MM-dd HH:mm): ");
        String timeStr = scanner.nextLine();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        Date startTime;
        try {
            startTime = sdf.parse(timeStr);
        } catch (ParseException e) {
            System.out.println("时间格式错误！");
            return;
        }

        // 检查时间是否在当前时间之后
        if (startTime.before(new Date())) {
            System.out.println("开始时间不能早于当前时间！");
            return;
        }

        // 检查影厅是否在该时间段已被占用
        if (ScreeningService.isHallOccupied(hallId, startTime, DBUtils.getMovieById(movieId).getDuration())) {
            System.out.println("该影厅在指定时间已被占用！");
            return;
        }

        System.out.print("请输入票价: ");
        double price;
        try {
            price = scanner.nextDouble();
            scanner.nextLine(); // 消费换行符
        } catch (InputMismatchException e) {
            System.out.println("输入错误，请输入数字！");
            scanner.nextLine(); // 清除错误输入
            return;
        }

        Screening newScreening = new Screening(screeningId, movieId, hallId, startTime, price);
        DBUtils.addScreening(newScreening);

        // 记录日志
        String logId = "LOG" + System.currentTimeMillis();
        String details = "添加新场次: " + screeningId + "，电影: " + DBUtils.getMovieById(movieId).getTitle();
        DBUtils.addLogEntry(new LogEntry(logId, manager.getUsername(), "ADD_SCREENING", details));

        System.out.println("场次添加成功！");
    }

    private static void updateScreening(User manager) {
        System.out.println("\n=== 修改场次信息 ===");
        System.out.print("请输入要修改的场次ID: ");
        String screeningId = scanner.nextLine();

        Screening screening = DBUtils.getScreeningById(screeningId);
        if (screening == null) {
            System.out.println("场次不存在！");
            return;
        }

        System.out.println("当前场次信息:");
        System.out.println("电影ID: " + screening.getMovieId());
        System.out.println("影厅ID: " + screening.getHallId());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        System.out.println("开始时间: " + sdf.format(screening.getStartTime()));
        System.out.println("票价: " + screening.getPrice());

        // 显示所有电影供选择
        listAllMovies();
        System.out.print("请输入新电影ID(不修改请按回车): ");
        String newMovieId = scanner.nextLine();
        if (newMovieId.isEmpty()) {
            newMovieId = screening.getMovieId();
        } else if (DBUtils.getMovieById(newMovieId) == null) {
            System.out.println("电影不存在，电影ID未修改！");
            newMovieId = screening.getMovieId();
        }

        // 显示所有影厅供选择
        listAllHalls();
        System.out.print("请输入新影厅ID(不修改请按回车): ");
        String newHallId = scanner.nextLine();
        if (newHallId.isEmpty()) {
            newHallId = screening.getHallId();
        } else if (DBUtils.getHallById(newHallId) == null) {
            System.out.println("影厅不存在，影厅ID未修改！");
            newHallId = screening.getHallId();
        }

        System.out.print("请输入新开始时间(格式: yyyy-MM-dd HH:mm，不修改请按回车): ");
        String timeStr = scanner.nextLine();
        Date newStartTime = screening.getStartTime();
        if (!timeStr.isEmpty()) {
            try {
                newStartTime = sdf.parse(timeStr);

                // 检查时间是否在当前时间之后
                if (newStartTime.before(new Date())) {
                    System.out.println("开始时间不能早于当前时间，时间未修改！");
                    newStartTime = screening.getStartTime();
                } else if (!newHallId.equals(screening.getHallId()) ||
                        !newStartTime.equals(screening.getStartTime())) {
                    // 检查影厅是否在该时间段已被占用
                    int duration = DBUtils.getMovieById(newMovieId).getDuration();
                    if (ScreeningService.isHallOccupied(newHallId, newStartTime, duration, screeningId)) {
                        System.out.println("该影厅在指定时间已被占用，时间未修改！");
                        newStartTime = screening.getStartTime();
                    }
                }
            } catch (ParseException e) {
                System.out.println("时间格式错误，时间未修改！");
            }
        }

        System.out.print("请输入新票价(不修改请输入0): ");
        double newPrice = screening.getPrice();
        try {
            double inputPrice = scanner.nextDouble();
            scanner.nextLine(); // 消费换行符
            if (inputPrice > 0) {
                newPrice = inputPrice;
            }
        } catch (InputMismatchException e) {
            System.out.println("输入错误，票价未修改！");
            scanner.nextLine(); // 清除错误输入
        }

        // 更新场次信息
        screening.setMovieId(newMovieId);
        screening.setHallId(newHallId);
        screening.setStartTime(newStartTime);
        screening.setPrice(newPrice);

        boolean success = DBUtils.updateScreening(screening);
        if (success) {
            // 记录日志
            String logId = "LOG" + System.currentTimeMillis();
            String details = "场次 " + screeningId + " 信息更新";
            DBUtils.addLogEntry(new LogEntry(logId, manager.getUsername(), "UPDATE_SCREENING", details));

            System.out.println("场次信息修改成功！");
        } else {
            System.out.println("场次信息修改失败！");
        }
    }

    private static void deleteScreening(User manager) {
        System.out.println("\n=== 删除场次 ===");
        System.out.print("请输入要删除的场次ID: ");
        String screeningId = scanner.nextLine();

        Screening screening = DBUtils.getScreeningById(screeningId);
        if (screening == null) {
            System.out.println("场次不存在！");
            return;
        }

        // 检查是否已有售票
        List<Ticket> tickets = DBUtils.getTicketsByScreeningId(screeningId);
        if (!tickets.isEmpty()) {
            System.out.println("无法删除，该场次已有售票记录！");
            return;
        }

        boolean success = DBUtils.deleteScreening(screeningId);
        if (success) {
            // 记录日志
            String logId = "LOG" + System.currentTimeMillis();
            String details = "删除场次: " + screeningId + "，电影: " + DBUtils.getMovieById(screening.getMovieId()).getTitle();
            DBUtils.addLogEntry(new LogEntry(logId, manager.getUsername(), "DELETE_SCREENING", details));

            System.out.println("场次删除成功！");
        } else {
            System.out.println("场次删除失败！");
        }
    }

    private static void viewSalesStatistics() {
        System.out.println("\n=== 销售统计 ===");
        System.out.println("1. 按电影统计");
        System.out.println("2. 按日期统计");
        System.out.println("3. 返回上一级");
        System.out.print("请选择: ");

        int choice;
        try {
            choice = scanner.nextInt();
            scanner.nextLine(); // 消费换行符
        } catch (InputMismatchException e) {
            System.out.println("输入错误，请输入数字1-3！");
            scanner.nextLine(); // 清除错误输入
            return;
        }

        switch (choice) {
            case 1:
                statisticsByMovie();
                break;
            case 2:
                statisticsByDate();
                break;
            case 3:
                return;
            default:
                System.out.println("无效选择，请重试！");
        }
    }

    private static void statisticsByMovie() {
        System.out.println("\n=== 按电影销售统计 ===");
        Map<String, Integer> movieSales = new HashMap<>();
        Map<String, Double> movieRevenue = new HashMap<>();

        // 初始化统计数据
        for (Movie movie : DBUtils.getAllMovies()) {
            movieSales.put(movie.getMovieId(), 0);
            movieRevenue.put(movie.getMovieId(), 0.0);
        }

        // 统计售票数据
        for (Ticket ticket : DBUtils.getAllTickets()) {
            if (!ticket.isRefunded()) {
                Screening screening = ticket.getScreening();
                if (screening != null) {
                    String movieId = screening.getMovieId();
                    double price = screening.getPrice();
                    // 儿童票半价
                    if (ticket.isChildTicket()) {
                        price /= 2;
                    }

                    movieSales.put(movieId, movieSales.getOrDefault(movieId, 0) + 1);
                    movieRevenue.put(movieId, movieRevenue.getOrDefault(movieId, 0.0) + price);
                }
            }
        }

        // 显示统计结果
        System.out.println("电影名称\t售票数\t票房收入");
        for (Movie movie : DBUtils.getAllMovies()) {
            String movieId = movie.getMovieId();
            System.out.println(
                    movie.getTitle() + "\t" +
                            movieSales.get(movieId) + "\t" +
                            String.format("%.2f", movieRevenue.get(movieId))
            );
        }
    }

    private static void statisticsByDate() {
        System.out.println("\n=== 按日期销售统计 ===");
        Map<String, Integer> dateSales = new HashMap<>();
        Map<String, Double> dateRevenue = new HashMap<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        // 统计售票数据
        for (Ticket ticket : DBUtils.getAllTickets()) {
            if (!ticket.isRefunded()) {
                String date = sdf.format(ticket.getPurchaseTime());
                Screening screening = ticket.getScreening();
                if (screening != null) {
                    double price = screening.getPrice();
                    // 儿童票半价
                    if (ticket.isChildTicket()) {
                        price /= 2;
                    }

                    dateSales.put(date, dateSales.getOrDefault(date, 0) + 1);
                    dateRevenue.put(date, dateRevenue.getOrDefault(date, 0.0) + price);
                }
            }
        }

        // 显示统计结果
        System.out.println("日期\t\t售票数\t票房收入");
        List<String> sortedDates = new ArrayList<>(dateSales.keySet());
        Collections.sort(sortedDates);

        for (String date : sortedDates) {
            System.out.println(
                    date + "\t" +
                            dateSales.get(date) + "\t" +
                            String.format("%.2f", dateRevenue.get(date))
            );
        }
    }
}

// 前台菜单类
class FrontDeskMenu {
    private static Scanner scanner = new Scanner(System.in);

    public static void showMenu(User frontDesk) {
        while (true) {
            System.out.println("\n=== 前台菜单 ===");
            System.out.println("1. 售票");
            System.out.println("2. 退票");
            System.out.println("3. 查看场次");
            System.out.println("4. 查看电影");
            System.out.println("5. 修改密码");
            System.out.println("6. 退出登录");
            System.out.print("请选择: ");

            int choice;
            try {
                choice = scanner.nextInt();
                scanner.nextLine(); // 消费换行符
            } catch (InputMismatchException e) {
                System.out.println("输入错误，请输入数字1-6！");
                scanner.nextLine(); // 清除错误输入
                continue;
            }

            switch (choice) {
                case 1:
                    sellTicket(frontDesk);
                    break;
                case 2:
                    refundTicket(frontDesk);
                    break;
                case 3:
                    ManagerMenu.listAllScreenings();
                    break;
                case 4:
                    ManagerMenu.listAllMovies();
                    break;
                case 5:
                    AdminMenu.changePassword(frontDesk);
                    break;
                case 6:
                    System.out.println("退出登录成功！");
                    return;
                default:
                    System.out.println("无效选择，请重试！");
            }
        }
    }

    private static void sellTicket(User frontDesk) {
        System.out.println("\n=== 售票 ===");
        // 显示所有场次供选择
        ManagerMenu.listAllScreenings();

        System.out.print("请输入要售票的场次ID: ");
        String screeningId = scanner.nextLine();

        Screening screening = DBUtils.getScreeningById(screeningId);
        if (screening == null) {
            System.out.println("场次不存在！");
            return;
        }

        // 检查场次是否已过期
        if (screening.getStartTime().before(new Date())) {
            System.out.println("该场次已过期，无法售票！");
            return;
        }

        // 获取已售座位
        List<Ticket> soldTickets = DBUtils.getTicketsByScreeningId(screeningId);
        Set<String> soldSeats = new HashSet<>();
        for (Ticket ticket : soldTickets) {
            soldSeats.add(ticket.getSeatNumber());
        }

        Hall hall = DBUtils.getHallById(screening.getHallId());
        int availableSeats = hall.getCapacity() - soldTickets.size();
        System.out.println("当前场次可售座位: " + availableSeats + " / " + hall.getCapacity());

        System.out.print("请输入要出售的票数: ");
        int ticketCount;
        try {
            ticketCount = scanner.nextInt();
            scanner.nextLine(); // 消费换行符
        } catch (InputMismatchException e) {
            System.out.println("输入错误，请输入数字！");
            scanner.nextLine(); // 清除错误输入
            return;
        }

        if (ticketCount <= 0 || ticketCount > availableSeats) {
            System.out.println("票数无效！");
            return;
        }

        // 处理每张票的销售
        for (int i = 0; i < ticketCount; i++) {
            System.out.println("\n--- 第 " + (i + 1) + " 张票 ---");

            // 获取座位号
            String seatNumber;
            while (true) {
                System.out.print("请输入座位号: ");
                seatNumber = scanner.nextLine().trim();

                if (seatNumber.isEmpty()) {
                    System.out.println("座位号不能为空！");
                    continue;
                }

                if (soldSeats.contains(seatNumber)) {
                    System.out.println("该座位已售出，请重新选择！");
                    continue;
                }

                break;
            }

            // 判断是否为儿童票（身高<1.2米）
            System.out.print("是否是儿童票? (y/n): ");
            String isChildInput = scanner.next().trim().toLowerCase();
            scanner.nextLine(); // 消费换行符
            boolean isChild = isChildInput.equals("y");

            // 创建票
            String ticketId = "T" + System.currentTimeMillis() + i;
            Ticket newTicket = new Ticket(ticketId, screeningId, seatNumber, isChild, new Date());
            DBUtils.addTicket(newTicket);

            // 更新已售座位
            soldSeats.add(seatNumber);

            // 计算票价
            double price = screening.getPrice();
            if (isChild) {
                price /= 2;
            }

            // 显示票信息
            System.out.println("售票成功！");
            System.out.println("票ID: " + ticketId);
            System.out.println("电影: " + DBUtils.getMovieById(screening.getMovieId()).getTitle());
            System.out.println("影厅: " + hall.getName());
            System.out.println("座位: " + seatNumber);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
            System.out.println("时间: " + sdf.format(screening.getStartTime()));
            System.out.println("类型: " + (isChild ? "儿童票" : "成人票"));
            System.out.println("票价: " + price);

            // 记录日志
            String logId = "LOG" + System.currentTimeMillis() + i;
            String details = "售出票: " + ticketId + "，场次: " + screeningId + "，座位: " + seatNumber;
            DBUtils.addLogEntry(new LogEntry(logId, frontDesk.getUsername(), "SELL_TICKET", details));
        }
    }

    private static void refundTicket(User frontDesk) {
        System.out.println("\n=== 退票 ===");
        System.out.print("请输入要退的票ID: ");
        String ticketId = scanner.nextLine();

        boolean success = TicketService.refundTicket(ticketId, frontDesk.getUsername());
        if (success) {
            System.out.println("退票成功！");
        } else {
            System.out.println("退票失败！");
        }
    }
}

// 场次服务类
class ScreeningService {
    // 检查影厅是否在指定时间已被占用
    public static boolean isHallOccupied(String hallId, Date startTime, int durationMinutes) {
        return isHallOccupied(hallId, startTime, durationMinutes, null);
    }

    // 检查影厅是否在指定时间已被占用（排除当前场次ID）
    public static boolean isHallOccupied(String hallId, Date startTime, int durationMinutes, String excludeScreeningId) {
        long durationMillis = durationMinutes * 60 * 1000L;
        long endTimeMillis = startTime.getTime() + durationMillis;

        for (Screening screening : DBUtils.getAllScreenings()) {
            // 跳过要排除的场次
            if (excludeScreeningId != null && screening.getScreeningId().equals(excludeScreeningId)) {
                continue;
            }

            if (screening.getHallId().equals(hallId)) {
                long existingStart = screening.getStartTime().getTime();
                Movie existingMovie = DBUtils.getMovieById(screening.getMovieId());
                if (existingMovie == null) continue;

                long existingEnd = existingStart + existingMovie.getDuration() * 60 * 1000L;

                // 检查时间是否重叠
                if (!(endTimeMillis <= existingStart || startTime.getTime() >= existingEnd)) {
                    return true;
                }
            }
        }
        return false;
    }
}

// 票务服务类
class TicketService {
    // 退票处理
    public static boolean refundTicket(String ticketId, String operator) {
        Ticket ticket = DBUtils.getTicketById(ticketId);
        if (ticket == null) {
            System.out.println("票不存在！");
            return false;
        }

        if (ticket.isRefunded()) {
            System.out.println("该票已退过！");
            return false;
        }

        Date now = new Date();
        Date startTime = ticket.getScreening().getStartTime();

        // 检查是否在电影开始前1小时以上
        long oneHourBefore = startTime.getTime() - 60 * 60 * 1000L;
        if (now.after(new Date(oneHourBefore)) && now.before(startTime)) {
            System.out.println("电影开始前1小时内不允许退票！");
            return false;
        }

        // 检查电影是否已开始
        if (now.after(startTime)) {
            System.out.println("电影已开始，不能退票！");
            return false;
        }

        // 执行退票
        ticket.setRefunded(true);
        boolean success = DBUtils.updateTicket(ticket);

        if (success) {
            // 记录日志
            String logId = "LOG" + System.currentTimeMillis();
            String details = "退票: " + ticketId + "，场次: " + ticket.getScreeningId();
            DBUtils.addLogEntry(new LogEntry(logId, operator, "REFUND_TICKET", details));
        }

        return success;
    }
}
